const request = require('request');
const querystring = require('querystring');
const fs = require('fs');
const win = require('electron').remote.getCurrentWindow();
const { dialog } = require('electron').remote;
import store from '@/store/index';

var __alert = function () {
    var options = {
        title: 'Requester',
        type: 'warning',
        buttons: ["确定"],
        defaultId: 0,
        cancelId: 0,
        detail: str,
        message: ''
    }
    dialog.showMessageBoxSync(win, options)
};
var checkURL = function (URL) {
    var str = URL,
        Expression = /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w- .\/?%&=]*)?/,
        objExp = new RegExp(Expression);
    if (objExp.test(str) == true) {
        return true
    } else {
        return false
    }
};


var checkRequestlegal = function (data, IP, callback) {
    var sendOption = data;
    var getCacheStr = `var getCache = key => {
            var data = store.state.cache.cacheObj[key];
            return data;
        };`;
    store.dispatch('fun/getAllCodeString').then((functionCode) => {
        var res = {};
        if (!sendOption.url) {
            callback('url 不能为空', false);
            return;
        } else {
            res.url = sendOption.url;
        };
        res.ip = IP;
        res.after = sendOption.after;
        res.type = sendOption.type;
        if (res.type == 'DEL') {
            res.type = 'DELETE'
        };
        if (sendOption.bodyType == 0) {
            try {
                if (sendOption.body) {
                    var body = '';
                    eval(functionCode + getCacheStr + ';body = ' + sendOption.body);
                    res.body = body;
                } else {
                    res.body = {};
                };
            } catch (error) {
                callback('body处理错误 : ' + error, false);
                return;
            };
        } else if (sendOption.bodyType == 1) {
            try {
                var body = {};
                body = JSON.parse(sendOption.fromdata);
                var isError = false
                for (let i = 0; i < body.length; i++) {
                    const element = body[i];
                    if (!element.key) {
                        // console.log(!element.key);
                        isError = true;
                        break;
                    };
                };
                if (isError) {
                    throw '参数名不能为空';
                } else {
                    res.body = body;
                };
            } catch (error) {
                callback('form-Data 处理出现错误 : ' + error, false);
                return;
            };
        };
        res.bodyType = sendOption.bodyType;
        try {
            if (sendOption.header) {
                var header = '';
                eval(functionCode + getCacheStr + ';header = ' + sendOption.header);
                res.header = header;
            } else {
                res.header = {};
            };
        } catch (error) {
            callback('header处理错误 : ' + error, false);
            return;
        };
        try {
            if (sendOption.query) {
                var query = '';
                eval(functionCode + getCacheStr + ';query = ' + sendOption.query);
                res.query = query;
            } else {
                res.query = {};
            };
        } catch (error) {
            callback('query处理错误 : ' + error, false);
            return;
        };
        try {
            if (sendOption.rest) {
                var rest = '';
                eval(functionCode + getCacheStr + ';rest = ' + sendOption.rest);
                res.rest = rest;
            } else {
                res.rest = {};
            };
        } catch (error) {
            callback('rest处理错误 : ' + error, false);
            return;

        };
        try {
            if (sendOption.before) {
                var before = '';
                eval(functionCode + getCacheStr + ';' + sendOption.before);
                res.before = before;
            };
        } catch (error) {
            // this.$alert('请求预处理错误 : ' + error);
            callback('请求预处理错误 : ' + error, false);
        };

        res.after = sendOption.after;
        var UrlAns = checkURL(IP + res.url);
        if (UrlAns) {
            callback(false, res);
        } else {
            callback('URL 不合法，请检查 URL 的正确性', false);
        };
    });














};

var formatResponseData = function (data, dataMapping) {
    var items = {};
    for (const key in store.state.model.models) {
        if (store.state.model.models.hasOwnProperty(key)) {
            const element = store.state.model.models[key];
            items[element.key] = element;
        }
    };
    var formatMapping = {
        object: function (data, dataMapping) {
            var str = '{ // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
            var _DataMappingObj = {};
            for (let i = 0; i < dataMapping.children.length; i++) {
                const element = dataMapping.children[i];
                _DataMappingObj[element.key] = element;
            };
            for (const key in data) {
                if (data.hasOwnProperty(key) && _DataMappingObj.hasOwnProperty(key)) {
                    const element = data[key];
                    str += '\"' + key + '\" :' + recursiveData(element, _DataMappingObj[key]);
                } else if (data.hasOwnProperty(key)) {
                    const element = data[key];
                    str += '\"' + key + '\" :' + JSON.stringify(element) + ', \n';
                }
            };
            str += '}, \n';
            return str;
        },
        array: function (data, dataMapping) {
            var str = '[ // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
            for (let i = 0; i < data.length; i++) {
                const element = data[i];
                str += recursiveData(element, dataMapping.children);
            };
            str += '], \n';
            return str;
        },
        modelArray: function (data, modelMapping) {
            var str = '[ // ' + modelMapping.annotate + ' (' + modelMapping.type + ') \n';
            var __type = modelMapping.type.substring(modelMapping.type.indexOf('<') + 1, modelMapping.type.indexOf('>'));
            for (let i = 0; i < data.length; i++) {
                const element = data[i];
                var obj = items[__type];

                str += formatMapping['modelEvent'](element, items[__type]);
            };
            str += '], \n';
            return str;
        },
        modelEvent: function (data, modelMapping) {
            var str = '{ // ' + modelMapping.name + ' (' + modelMapping.key + ') \n';
            var modelItems = modelMapping.itemArray;
            var itemObj = {};
            for (let i = 0; i < modelItems.length; i++) {
                const element = modelItems[i];
                itemObj[element.key] = element;
            };
            for (const key in data) {
                if (data.hasOwnProperty(key) && itemObj.hasOwnProperty(key)) {
                    const element = data[key];
                    var _type = itemObj[key].type;
                    if (_type.indexOf('List') >= 0) {
                        var __type = _type.substring(_type.indexOf('<') + 1, _type.indexOf('>'));
                        str += '\"' + key + '\" :' + formatMapping['modelArray'](element, items[__type])
                    } else if (items.hasOwnProperty(_type)) {
                        str += '\"' + key + '\" :' + formatMapping['modelObject'](element, items[_type])
                    } else {
                        str += '\"' + key + '\" :\'' + element + ' \',  // ' + itemObj[key].annotate + ' (' + itemObj[key].type + ') \n';
                    };
                } else {
                    const element = data[key];
                    str += '\"' + key + '\" :' + JSON.stringify(element) + ', \n';
                };
            };
            str += '}, \n';
            return str;
        },
        modelObject: function (data, modelMapping) {
            var str = '{ // ' + modelMapping.annotate + ' (' + modelMapping.type + ') \n';
            var modelItems = items[modelMapping.type].itemArray;
            var itemObj = {};
            for (let i = 0; i < modelItems.length; i++) {
                const element = modelItems[i];
                itemObj[element.key] = element;
            };
            for (const key in data) {
                if (data.hasOwnProperty(key) && itemObj.hasOwnProperty(key)) {
                    const element = data[key];
                    var _type = itemObj[key].type;
                    if (_type.indexOf('List') >= 0) {
                        var __type = _type.substring(_type.indexOf('<') + 1, _type.indexOf('>'));
                        str += '\"' + key + '\" :' + formatMapping['modelArray'](element, items[__type])
                    } else if (items.hasOwnProperty(_type)) {
                        str += '\"' + key + '\" :' + formatMapping['modelObject'](element, items[_type])
                    } else {
                        str += '\"' + key + '\" :\'' + element + ' \',  // ' + itemObj[key].annotate + ' (' + itemObj[key].type + ') \n';
                    };
                } else {
                    const element = data[key];
                    str += '\"' + key + '\" :' + JSON.stringify(element) + ', \n';
                };
            };
            str += '}, \n';
            return str;
        },
        model: function (data, dataMapping) {
            var str = '{ // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
            var modelItems = items[dataMapping.model.key].itemArray;
            var itemObj = {};
            for (let i = 0; i < modelItems.length; i++) {
                const element = modelItems[i];
                itemObj[element.key] = element;
            };

            for (const key in data) {
                if (data.hasOwnProperty(key) && itemObj.hasOwnProperty(key)) {
                    const element = data[key];
                    var _type = itemObj[key].type;
                    if (_type.indexOf('List') >= 0) {
                        var __type = _type.substring(_type.indexOf('<') + 1, _type.indexOf('>'));
                        str += '\"' + key + '\" :' + formatMapping['modelArray'](element, itemObj[key])
                    } else if (items.hasOwnProperty(_type)) {
                        str += '\"' + key + '\" :' + formatMapping['modelObject'](element, itemObj[key])
                    } else {
                        str += '\"' + key + '\" :\'' + element + ' \',  // ' + itemObj[key].annotate + ' (' + itemObj[key].type + ') \n';
                    };
                } else {
                    const element = data[key];
                    str += '\"' + key + '\" :' + JSON.stringify(element) + ', \n';
                };
            };
            str += '}, \n';
            return str;
        },
        string: function (data, dataMapping) {
            return '\"' + data + '\" ,  // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
        },
        int: function (data, dataMapping) {
            return '\"' + data + '\" ,  // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
        },
        other: function (data, dataMapping) {
            return '\"' + data + '\" ,  // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
        },
        none: function (data, dataMapping) {
            return '\"' + data + '\" ,  // ' + dataMapping.annotate + ' (' + dataMapping.type + ') \n';
        },
    };

    var recursiveData = function (data, dataMapping) {
        return formatMapping[dataMapping.type](data, dataMapping);
    };
    var output,
        opts = {
            // brace_style : "expand"
        };
    opts.indent_char = ' ';
    opts.preserve_newlines = "-1";
    var str = recursiveData(data, dataMapping);
    var output = js_beautify(str, opts);

    return output;
};
var requestEvent = function (_res, dataMapping, callback) {
    var res = JSON.parse(JSON.stringify(_res));
    var requestData = {
        method: res.type,
        headers: res.header,
        time: true,
        jar: true
    };
    if (res.bodyType == '0') {
        requestData.json = res.body;
    } else if (res.bodyType == '1') {
        var fromData = {};
        for (let i = 0; i < res.body.length; i++) {
            const item = res.body[i];
            if (item.type == 'file') {
                fromData[item.key] = fs.createReadStream(item.url);
            } else {
                fromData[item.key] = item.value;
            }
        };
        requestData.preambleCRLF = true;
        requestData.postambleCRLF = true;
        requestData.formData = fromData;
    };
    var _url = res.url.split('/');
    for (let i = 0; i < _url.length; i++) {
        var element = _url[i];
        var str = element.match(/(?<={).+(?=})/);
        if (str && str.length > 0) {
            if (res.rest.hasOwnProperty(str[0])) {
                let item = res.rest[str[0]];
                _url[i] = item;
            };
        } else {
            var re = element.match(/(?<=:).*/);
            if (re && re.length > 0) {
                if (res.rest.hasOwnProperty(re[0])) {
                    let item = res.rest[re[0]];
                    _url[i] = item;
                };
            }
        };
    };
    var $url = _url.join('/');
    requestData.url = res.ip + encodeURI($url);
    var queryString = querystring.stringify(res.query);
    if (queryString) {
        requestData.url += '?' + queryString;
    };

    var _request = request(requestData, (error, response, body) => {
        if (error) {
            callback({
                error,
                response,
                body,
            });
        } else {
            function looks_like_html(source) {
                var trimmed = source.replace(/^[ \t\n\r]+/, '');
                return trimmed && (trimmed.substring(0, 1) === '<');
            };
            function reconvert(str) {
                str = str.replace(/(\\u)(\w{1,4})/gi, function ($0) {
                    return (String.fromCharCode(parseInt((escape($0).replace(/(%5Cu)(\w{1,4})/g, "$2")), 16)));
                });
                str = str.replace(/(&#x)(\w{1,4});/gi, function ($0) {
                    return String.fromCharCode(parseInt(escape($0).replace(/(%26%23x)(\w{1,4})(%3B)/g, "$2"), 16));
                });
                str = str.replace(/(&#)(\d{1,6});/gi, function ($0) {
                    return String.fromCharCode(parseInt(escape($0).replace(/(%26%23)(\d{1,6})(%3B)/g, "$2")));
                });
                return str;
            };


            store.dispatch('fun/getAllCodeString').then((functionCode) => {
                var getCacheStr = `;var getCache = key => {
                        var data = store.state.cache.cacheObj[key];
                        return data;
                    };`;

                var setCacheStr = `;var setCache = (key,value) => {
                        store.dispatch('cache/updataCache',{
                            key : key,
                            value : value,
                        })
                    };`;
                // console.log(error, response, body);
                try {
                    if (body) {
                        var res = body;
                        eval(functionCode + getCacheStr + setCacheStr + ';' + _res.after);
                    } else {
                        res = '';
                    };
                } catch (error) {
                    __alert('after处理错误 : ' + error);
                    return;
                };

                var output = '';
                var looksLikeHtml = false;
                if (typeof body == 'object') {
                    var output = js_beautify(JSON.stringify(res), {});
                    try {
                        var str = formatResponseData(res, dataMapping);
                        output = str;
                    } catch (error) {
                        console.error(error);
                    };
                } else if (looks_like_html(res)) {
                    looksLikeHtml = true;
                    var output = html_beautify(res, {});
                } else {
                    var output = res.toString();
                };
                if (output) {
                    output = reconvert(output);
                };
                callback({
                    error,
                    looksLikeHtml,
                    response,
                    body,
                    output,
                });
                // this.Response.setValue(output);
                // this.lastResponse = output;
            });
        };
    });
    return _request;
}

export default {
    checkURL,
    checkRequestlegal,
    requestEvent,
    formatResponseData
}


